package com.example.activiti.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.example.activiti.common.exclusion.UserDetailsUtil;
import com.example.activiti.common.core.page.PageDomain;
import com.example.activiti.domain.ActWorkflowFormData;
import com.example.activiti.domain.dto.ActTaskDTO;
import com.example.activiti.domain.dto.ActWorkflowFormDataDTO;
import com.example.activiti.service.IActTaskService;
import com.example.activiti.service.IActWorkflowFormDataService;
import com.github.pagehelper.Page;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.BaseElement;
import org.activiti.bpmn.model.FormProperty;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Administrator
 */
@Service
public class ActTaskServiceImpl implements IActTaskService {

    @Resource
    private TaskRuntime taskRuntime;
    @Resource
    private TaskService taskService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private UserDetailsUtil userDetailsUtil;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private IActWorkflowFormDataService actWorkflowFormDataService;

    @Override
    public Page<ActTaskDTO> selectTaskListByUserId(PageDomain pageDomain, String userId) {
        userDetailsUtil.loginAs(userId);
        Page<ActTaskDTO> list = new Page<>();
        org.activiti.api.runtime.shared.query.Page<Task> pageTasks = taskRuntime.tasks(Pageable.of((pageDomain.getPageNum() - 1) * pageDomain.getPageSize(), pageDomain.getPageSize()));
        List<Task> tasks = pageTasks.getContent();
        int totalItems = pageTasks.getTotalItems();
        list.setTotal(totalItems);
        if (totalItems != 0) {
            Set<String> processInstanceIdIds = tasks.parallelStream().map(Task::getProcessInstanceId).collect(Collectors.toSet());
            List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIdIds).list();
            List<ActTaskDTO> taskDataList = tasks.stream()
                    .map(t -> new ActTaskDTO(t, processInstanceList.parallelStream().filter(pi -> t.getProcessInstanceId().equals(pi.getId())).findAny().get()))
                    .collect(Collectors.toList());
            list.addAll(taskDataList);
        }
        return list;


//        Page<ActTaskDTO> list = new Page<>();
//        // 目标类
//        List<org.activiti.engine.task.Task> tasks = taskService.createTaskQuery()
//                .taskCandidateOrAssigned(userId)
//                .listPage((pageDomain.getPageNum() - 1) * pageDomain.getPageSize(), pageDomain.getPageSize());
//        int totalItems = tasks.size();
//        list.setTotal(totalItems);
//        if (totalItems != 0) {
//            Set<String> processInstanceIdIds = tasks.parallelStream().map(TaskInfo::getProcessInstanceId).collect(Collectors.toSet());
//            List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIdIds).list();
//            List<ActTaskDTO> actTaskDataList = tasks.stream()
//                    .map(t -> new ActTaskDTO(t, processInstanceList.parallelStream().filter(pi -> t.getProcessInstanceId().equals(pi.getId())).findAny().get()))
//                    .collect(Collectors.toList());
//            list.addAll(actTaskDataList);
//        }
//        return list;
    }

    @Override
    public List<String> formDataShow(String taskId) {
        org.activiti.engine.task.Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        // Task task = taskRuntime.task(taskId);
            /*  ------------------------------------------------------------------------------
            FormProperty_0ueitp2--__!!类型--__!!名称--__!!是否参数--__!!默认值
            例子：
            FormProperty_0lovri0--__!!string--__!!姓名--__!!f--__!!同意!!__--驳回
            FormProperty_1iu6onu--__!!int--__!!年龄--__!!s

            默认值：无、字符常量、FormProperty_开头定义过的控件ID
            是否参数：f为不是参数，s是字符，t是时间(不需要int，因为这里int等价于string)
            注：类型是可以获取到的，但是为了统一配置原则，都配置到
            */

        //注意!!!!!!!!:表单Key必须要任务编号一模一样，因为参数需要任务key，但是无法获取，只能获取表单key“task.getFormKey()”当做任务key
        String formKey = task.getFormKey();
        String processDefinitionId = task.getProcessDefinitionId();
        UserTask userTask = (UserTask) repositoryService.getBpmnModel(processDefinitionId).getFlowElement(formKey);
        if (userTask == null) {
            return null;
        }
        List<FormProperty> formProperties = userTask.getFormProperties();
        return formProperties.stream().map(BaseElement::getId).collect(Collectors.toList());
    }

    @Override
    public int formDataSave(String taskId, String userId, List<ActWorkflowFormDataDTO> formData) {
        userDetailsUtil.loginAs(userId);
        Task task = taskRuntime.task(taskId);
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        // 没有任何参数
        boolean hasVariables = false;
        HashMap<String, Object> variables = new HashMap<>(4);
        // 前端传来的字符串，拆分成每个控件
        List<ActWorkflowFormData> dataList = new ArrayList<>();
        for (ActWorkflowFormDataDTO awf : formData) {
            ActWorkflowFormData actWorkflowFormData = new ActWorkflowFormData(processInstance.getBusinessKey(), awf, task);
            String idStr = System.currentTimeMillis() + "" + RandomUtil.randomLong(1000, 9999);
            actWorkflowFormData.setId(Long.parseLong(idStr));
            dataList.add(actWorkflowFormData);
            // 构建参数集合
            if (!"f".equals(awf.getControlIsParam())) {
                variables.put(awf.getControlId(), awf.getControlValue());
                hasVariables = true;
            }
        }
        // for结束
        if (task.getAssignee() == null) {
            taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
        }
        if (hasVariables) {
            //带参数完成任务
            taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskId)
                    .withVariables(variables)
                    .build());
        } else {
            taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskId)
                    .build());
        }
        // 写入数据库
        return actWorkflowFormDataService.insertActWorkflowFormDatas(userId, userId, dataList);
    }
}
